/**
 * 
 */
package com.seeyon.apps.quartz.util;

import com.seeyon.ctp.common.quartz.MutiQuartzJobNameException;
import com.seeyon.ctp.common.quartz.NoSuchQuartzJobBeanException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;

/**
 * 步骤：<br>
 * 
 * 1. 定义任务处理器
 * <pre>
 * <code>
 *   class ABCQuartz implement QuartzJob{
 *     public void execute(Map&lt;String, String&gt; parameters){
 *         Long id = parameters.get("id");
 *         ...
 *     }
 *   }
 *   
 *   &lt;bean name=&quot;abcQuartz&quot; class=&quot;package.ABCQuartz&quot; /&gt;
 * </code>
 * </pre>
 * 2. 生成任务
 * <pre>
 * <code>
 * Map&lt;String, String&gt; parameters = new HashMap&lt;String, String&gt;();
 * parameters.put(&quot;id&quot;, String.valueOf(id));
 * QuartzHolder.newQuartzJob(&quot;jobName&quot;, new Date(109, 1, 1), &quot;abcQuartz&quot;, parameters);
 * </code>
 * </pre>
 * 
 * @author <a href="mailto:tanmf@seeyon.com">Tanmf</a>
 * @version 1.0 2008-11-25
 */
public class QuartzCronUtil {

	private static final Log log = LogFactory.getLog(QuartzCronUtil.class);

	/**
	 * 创建每天的定时任务，时间以beginTime为准
	 * @param beginTime
	 * @return
	 */
	public static String getCronPerDay(Date beginTime) {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);

		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);

		String cronExpression = second + " " + minute + " " + hourOfDay + " " + "*" + " * ?";
		return cronExpression;
	}

	/**
	 * 创建每周的定时任务，星期几时间以beginTime那天所处的星期几为准
	 * @return
	 */
	public static String getCronByWeek(Date beginTime) {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);
		
		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);
		int dayOfWeek = gc.get(GregorianCalendar.DAY_OF_WEEK);
		
		String cronExpression = second + " " + minute + " " + hourOfDay + " ? * " + dayOfWeek;
		return cronExpression;
	}

	/**
	 * 创建每月的定时任务，“日”以beginTime那天所处的“日”为准，如果是31日，则自动顺延
	 *
	 * @param beginTime
	 * @return
	 */
	public static String getCronByMonth(Date beginTime) {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);

		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);
		int dayOfMonth = gc.get(GregorianCalendar.DAY_OF_MONTH);

		String cronExpression = second + " " + minute + " " + hourOfDay + " " + dayOfMonth + " * ?";
		return cronExpression;
	}

	/**
	 * 创建每月最后一天执行的定时任务。
	 */
	public static String getCronByEndOfMonth(Date beginTime) {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);
		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);
		String cronExpression = second + " " + minute + " " + hourOfDay + " L * ?";
		return cronExpression;
	}

	/**
	 * 创建每月倒数第N天指定时间执行的定时任务。
	 * @param beginTime 开始时间 执行的具体时间（时分秒按照该参数相应的时分秒设定）
	 * @param days 每月倒数第几天，比如2表示每月的倒数第2天
	 */
	private static String newQuartzJobEndOfMonth(Date beginTime, int days) {
		if(days < 1 || days > 25){
			log.warn("倒数第几天的参数传递不合法（取值范围：[1-25]）,当前传入的值为：" + days + "，系统自动将该参数设置为：1");
			days = 1;
		}
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);

		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);

		String cronExpression = second + " " + minute + " " + hourOfDay + " " + days + "L * ?";
		return cronExpression;
	}

	/**
	 * 创建每季度的定时任务，“日”以beginTime那天所处的“日”为准，如果是31日，则自动顺延
	 *
	 * @param beginTime
	 * @return
	 */
	public static String getCronBySeason(Date beginTime) {
		Date endTime = null;
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);

		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);
		int dayOfMonth = gc.get(GregorianCalendar.DAY_OF_MONTH);
		int month = gc.get(GregorianCalendar.MONTH) + 1;
		int start = month % 3;
		start = start ==0 ? 3 :start;
		String cronExpression = second + " " + minute + " " + hourOfDay + " " + dayOfMonth + " " + start + "/3 ?";
		return cronExpression;
	}

	/**
	 * 创建每半年执行的定时任务。
	 * @param beginTime
	 * @return
	 * @throws MutiQuartzJobNameException
	 * @throws NoSuchQuartzJobBeanException
	 */
	public static String getCronByPerHalfYear(Date beginTime) {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);
		
		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);
		int dayOfMonth = gc.get(GregorianCalendar.DAY_OF_MONTH);
		int month = gc.get(GregorianCalendar.MONTH) + 1;
		int start = month % 6;
		start = start ==0 ? 6 :start;		
		String cronExpression = second + " " + minute + " " + hourOfDay + " " + dayOfMonth + " " + start + "/6 ?";
		return cronExpression;
	}
	/**
	 * 创建每半年末执行的定时任务。
	 * @param groupName
	 * @param jobName
	 * @param beginTime
	 * @param endTime
	 * @param jobBeanId
	 * @param parameters
	 * @return
	 * @throws MutiQuartzJobNameException
	 * @throws NoSuchQuartzJobBeanException
	 */
	public static String getCronByEndOfHalfYear(String groupName,
			String jobName, Date beginTime, Date endTime, String jobBeanId,
			Map<String, String> parameters) throws MutiQuartzJobNameException,
            NoSuchQuartzJobBeanException {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);
		
		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);

		String cronExpression = second + " " + minute + " " + hourOfDay + " " + "L" + " " + "6,12" + " ?";
		return cronExpression;
	}

	/**
	 * 创建每季度最后一天执行的定时任务。
	 * @param groupName
	 * @param jobName
	 * @param beginTime
	 * @param endTime
	 * @param jobBeanId
	 * @param parameters
	 * @return
	 * @throws MutiQuartzJobNameException
	 * @throws NoSuchQuartzJobBeanException
	 */
	public static String getCronByEndOfSeason(String groupName,
			String jobName, Date beginTime, Date endTime, String jobBeanId,
			Map<String, String> parameters) throws MutiQuartzJobNameException,
            NoSuchQuartzJobBeanException {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);
		
		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);

		String cronExpression = second + " " + minute + " " + hourOfDay + " L 3,6,9,12 ?";
		return cronExpression;
	}
	/**
	 * 创建每年度的定时任务，“月-日”以beginTime那天所处的“月日”为准，如果是2-29日，则自动顺延为3-1
	 *
	 * @param beginTime
	 * @return
	 */
	public static String getCronByPerYear(Date beginTime) {
		GregorianCalendar gc = new GregorianCalendar();
		gc.setTime(beginTime);
		int second = gc.get(GregorianCalendar.SECOND);
		int minute = gc.get(GregorianCalendar.MINUTE);
		int hourOfDay = gc.get(GregorianCalendar.HOUR_OF_DAY);
		int dayOfMonth = gc.get(GregorianCalendar.DAY_OF_MONTH);
		int month = gc.get(GregorianCalendar.MONTH) + 1;

		String cronExpression = second + " " + minute + " " + hourOfDay + " " + dayOfMonth + " " + month + " ? *";
		return cronExpression;
	}

}
